package org.springblade.common.tool;


import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Genius
 * @version 1.0.0
 * @ClassName UploadMinio.java
 * @createTime 2021年11月22日 20:16:00
 */
@Component
public class UploadMinioUtil {
	// 将要上传的bucket存储空间
	static String bucketName = "xn-policy";

	@Resource
	private MinioClient minioClient;


	public String fileRename(MultipartFile file) {
		// 获取原文件名 + 时间戳(System.currentTimeMillis())，作为上传文件的文件名
		// 分割字符串
		String[] circleSp = file.getOriginalFilename().split("\\.");
		//形成新的文件名
		String name = circleSp[0] + System.currentTimeMillis() + "." + circleSp[1];

		System.out.println(name);
		return name;
	}

	/**
	 * 查看存储bucket是否存在
	 *
	 * @return boolean
	 */
	public Boolean bucketExists(String bucketName) {
		Boolean found;
		try {
			found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
		} catch (Exception e) {
			//e.printStackTrace();
			return false;
		}
		return found;
	}

	/**
	 * 创建存储bucket
	 *
	 * @return Boolean
	 */
	public Boolean makeBucket(String bucketName) {
		try {
			minioClient.makeBucket(MakeBucketArgs.builder()
				.bucket(bucketName)
				.build());
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 删除存储bucket
	 *
	 * @return Boolean
	 */
	public Boolean removeBucket(String bucketName) {
		try {
			minioClient.removeBucket(RemoveBucketArgs.builder()
				.bucket(bucketName)
				.build());
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 获取全部bucket
	 */
	public List<Bucket> getAllBuckets() {
		try {
			return minioClient.listBuckets();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 文件上传
	 *
	 * @param file 文件
	 * @return Boolean
	 */
	public Boolean upload(MultipartFile file, String fileName) {

		try {
			PutObjectArgs objectArgs = PutObjectArgs.builder()
				.bucket(bucketName)
				.object(fileName)
				.contentType(file.getContentType())
				.stream(file.getInputStream(), file.getSize(), 0)
				.build();
			//文件名称相同会覆盖
			minioClient.putObject(objectArgs);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 预览图片
	 *
	 * @param fileName
	 * @return
	 */
	public String preview(String fileName) {
		// 查看文件地址
		GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(bucketName).object(fileName).method(Method.GET).build();
		try {
			String url = minioClient.getPresignedObjectUrl(build);
			return url;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 文件下载
	 *
	 * @param fileName 文件名称
	 * @param res      response
	 * @return Boolean
	 */
	public void download(String fileName, String original, HttpServletResponse res) {
		GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(fileName).build();
		try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
			byte[] buf = new byte[1024];
			int len;
			try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
				while ((len = response.read(buf)) != -1) {
					os.write(buf, 0, len);
				}
				os.flush();
				byte[] bytes = os.toByteArray();
				res.setCharacterEncoding("utf-8");
				//设置强制下载不打开
				res.setContentType("application/force-download");
				res.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(original, "UTF-8"));
				try (ServletOutputStream stream = res.getOutputStream()) {
					stream.write(bytes);
					stream.flush();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 查看文件对象
	 *
	 * @return 存储bucket内文件对象信息
	 */
	public List<Item> listObjects() {
		Iterable<Result<Item>> results = minioClient.listObjects(
			ListObjectsArgs.builder().bucket(bucketName).build());
		List<Item> items = new ArrayList<>();
		try {
			for (Result<Item> result : results) {
				items.add(result.get());
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return items;
	}

	/**
	 * 删除
	 *
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	public boolean remove(String fileName) {
		try {
			minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
		} catch (Exception e) {
			return false;
		}
		return true;
	}

	/**
	 * 批量删除文件对象(已测试）
	 *
	 * @param objects 对象名称集合
	 */
	public Iterable<Result<DeleteError>> removeObjects(List<String> objects) {
		List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
		Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
		try {
			for (Result<DeleteError> result : results) {
				result.get();
			}
		} catch (Exception e) {
		}
		return results;
	}

}
